package com.goodomen.garbage.common.utils;

import com.goodomen.garbage.common.persistence.model.system.SysPermission;
import org.apache.commons.lang3.StringUtils;

/**
 * @author : Zhao Da
 * @since : 2019/7/4 14:57
 */
public class BitMap {

    /**
     * 1byte = 8bit
     * 40bit = byte[5]
     */
    private byte[] bytes;
    private int length;

    public BitMap() {

    }

    public BitMap(byte[] bytes) {
        this.bytes = bytes;
    }

    /**
     * @param length 位图长度，实际可操作下标为[0,length)
     */
    public BitMap(int length){
        this.length = length;
        bytes = new byte[length%8==0 ? length/8 : length/8+1];
    }

    /**
     * 设置指定位的值
     */
    public void set(int index, boolean value){
        index -= 1;
        if(value) {
            //通过给定位index，先定位到对应byte
            //并根据value值进行不同位操作：
            //  1.如果value为true，则目标位应该做“或”运算。则需构建“目标位为1，其他为0”的操作数，为了只合理操作目标位，而不影响其他位
            //  2.如果value为false，则目标位应该做“与”运算。则需构建“目标位为0，其他为1”的操作数
            // bytes[index/8] = bytes[index/8] | (0b0001 << (index%8))
            bytes[index >> 3] |= 1 << (index & 7);
        } else {
            bytes[index >> 3] &= ~(1 << (index & 7));
        }
    }

    /**
     * 获取指定位的值
     */
    public boolean get(int index){
        index -= 1;
        int i = index & 7;
        //构建到index结束的低位掩码并做&运算（为了将高位置0），然后将结果一直右移直到目标位(index位)移到第1位
        //然后根据其值返回结果
        return (bytes[index >> 3] & (0b11111111>>>(7-i))) >> i != 0;
    }

    public byte[] getPermission(String permissions, SysPermission sysPermission) {
        String [] permissionArray = permissions.split(",");
        BitMap bitMap = new BitMap(sysPermission.getId());
        for (String permission : permissionArray) {
            if (StringUtils.isNotBlank(permission)) {
                bitMap.set(Integer.valueOf(permission), true);
            }
        }
        return bitMap.bytes;
    }

    @Override
    public String toString() {
        StringBuffer buffer = new StringBuffer("Bitmap[");
        for(int i=0;i<length;i++){
            buffer.append(get(i)).append(',');
        }
        if (bytes.length!=0) {
            buffer = buffer.deleteCharAt(buffer.length()-1);
        }
        buffer.append(']');
        return buffer.toString();
    }

}
